﻿#region License

// PentaBiz - Sustainable Software Development Framework Copyright (C) 2013 Zoltán Csizmazia
// 
// This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PentaBiz.Cloud.CloudDb.EntityModel.MetaModel;
using PentaBiz.Cloud.CloudDb.EntityModel.SystemModel;
using PentaBiz.Collections;

namespace PentaBiz.Cloud.CloudDb.Testing
{
    [TestClass]
    public class UnitTestCloudDbContext
    {
        [TestMethod]
        [TestCategory("CloudMetaDbContext")]
        public void TestIfCanCreateCloudDbContext()
        {
            var c = new MetaDbContext();

            Assert.IsNotNull(c, "CloudDbContext could not be null");

            c.SaveChanges();
        }

        [TestMethod]
        [TestCategory("CloudMetaDbContext")]
        public void TestIfCanLogin()
        {
            var c = new MetaDbContext();
            SystemToken securityToken = c.LoginUser("root", "SystemService", "secret");

            c.SaveChanges();

            Assert.IsNotNull(securityToken, "SystemToken could not be null after login");
            Assert.IsTrue(securityToken.ValidateExpiration(), "Token must pass ValidateExpiration");
            Assert.IsNotNull(securityToken.Token, "Token must be created");
            Assert.IsTrue(securityToken.ValidTillUtc > DateTime.UtcNow, "Token must be valid for a while");
        }


        [TestMethod]
        [TestCategory("CloudMetaDbContext")]
        public void TestEntityCanAuthenticate()
        {
            string token;

            using (var c = new MetaDbContext())
            {
                SystemToken securityToken = c.LoginUser("root", "SystemService", "secret");
                token = securityToken.Token;

                Assert.IsNotNull(securityToken);

                c.SaveChanges();
            }

            using (var c = new MetaDbContext())
            {
                SystemToken securityToken = c.AuthorizeUser("root", "SystemService", token);

                Assert.IsNotNull(securityToken);
                Assert.IsNotNull(securityToken.SystemUser);
                Assert.IsNotNull(securityToken.SystemScope);

                c.SaveChanges();
            }
        }


        [TestMethod]
        [TestCategory("CloudMetaDbContext")]
        public void TestAuthenticatedContextIsSettingScope()
        {
            string token;

            using (var c = new MetaDbContext())
            {
                SystemToken securityToken = c.LoginUser("root", "SystemService", "secret");
                token = securityToken.Token;

                Assert.IsNotNull(securityToken);

                c.SaveChanges();
            }

            using (var c = new MetaDbContext())
            {
                SystemToken securityToken = c.AuthorizeUser("root", "SystemService", token);

                MetaApplication app = MetaApplication.CreateSampleApplication("Hello_world");

                c.MetaApplications.Add(app);

                Assert.IsNotNull(app.SystemScope, "Security scope must be set on Set.Add()");

                c.SaveChanges();
            }
        }

        [TestMethod, TestCategory("CloudMetaDbContext")]
        public void TestUnauthenticatedContextIsFilteringUsers()
        {
            using (var c = new MetaDbContext())
            {
                c.LockContext();

                Assert.AreEqual(0, c.SystemUsers.Count(), "UnAuthorized context should return 0 SystemUsers");
            }
        }

        [TestMethod, TestCategory("CloudMetaDbContext")]
        public void TestUnauthenticatedContextIsFilteringAllUserTables()
        {
            //var exludedTable = new[] {"SystemScopes"};
            using (var c = new MetaDbContext())
            {
                c.LockContext();


                IEnumerable<PropertyInfo> propertyInfos =
                    DbContextReflection.ReflectDbSetProperties<MetaDbContext>();

                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    var value = (IQueryable) propertyInfo.GetValue(c, null);

                    try
                    {
                        Assert.AreEqual(0, value.CountUntyped(), "Query {0} should have returned 0 entity");
                    }
                    catch (TargetException)
                    {
                        Console.WriteLine("There is an error with the Entity filter condition. Context Property : {0}",
                                          propertyInfo.Name);
                        throw;
                    }
                }
            }
        }
    }
}